﻿using System;
using System.Security;
using System.Text.RegularExpressions;

namespace LeRenard
{
    /// <summary>
    /// Provides extension methods to interact with <see cref="String"/> objects.
    /// </summary>
    public static class StringExtensions
    {
        #region Formatting
        /// <summary>
        /// Replaces the format item in the specified string with the string representation of a corresponding object in a specified array.
        /// </summary>
        /// <param name="format">A composite format string.</param>
        /// <param name="args">An object array that contains zero or more objects to format.</param>
        /// <returns>The formatted string with string representations in place.</returns>
        /// <remarks>
        /// 1. The extensions method is not called 'Format', because this would clash with the static method 'Format' on the <see cref="String"/> class.
        /// 2. This is just a short-hand way to use the 'String.Format' method directly on a string instance.
        /// </remarks>
        public static string FormatWith(this string format, params object[] args)
        {
            return String.Format(format, args);
        }

        /// <summary>
        /// Replaces the format item in the specified string with the string representation of a corresponding object in a specified array.
        /// </summary>
        /// <param name="format">A composite format string.</param>
        /// <param name="formatProvider">An object that specifies culture-specific formatting information.</param>
        /// <param name="args">An object array that contains zero or more objects to format.</param>
        /// <returns>The formatted string with string representations in place.</returns>
        /// <remarks>
        /// 1. The extensions method is not called 'Format', because this would clash with the static method 'Format' on the <see cref="String"/> class.
        /// 2. This is just a short-hand way to use the 'String.Format' method directly on a string instance.
        /// </remarks>        
        public static string FormatWith(this string format, IFormatProvider formatProvider, params object[] args)
        {
            return String.Format(formatProvider, format, args);
        }
        #endregion

        #region Manipulation
        /// <summary>
        /// Removes all multiple whitespace characters, and replaces them with only one whitespace character.
        /// </summary>
        /// <param name="string">The string to remove multiple whitespaces from.</param>
        /// <returns>The given string with multiple whitespace between other characters removed, and replaced with only one whitespace character.</returns>
        public static string RemoveMultipleWhitespaces(this string @string)
        {
            if (@string == null)
                return @string;

            var cleanedString =
                Regex
                .Replace(@string, @"(\s)\s+", "$1");

            return cleanedString.Trim();
        }
        #endregion

        #region Converting
        /// <summary>
        /// Converts a <see cref="String"/> to a <see cref="SecureString"/>.
        /// </summary>
        /// <param name="string">The <see cref="String"/> to be converted.</param>
        /// <returns>A <see cref="SecureString"/> representation of the given <paramref name="string"/>.</returns>
        public static SecureString ToSecureString(this string @string)
        {
            ThrowIf.Null(() => @string);

            var secureString = new SecureString();

            foreach (var character in @string.ToCharArray())
                secureString.AppendChar(character);

            return secureString;
        }
        #endregion
    }
}
